/**
 * This file contains code for making the settings window for the
 *  FontSelector.
 */
package no.hig.ekm.ircclient;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GraphicsEnvironment;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ResourceBundle;
import java.util.prefs.Preferences;

import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.GroupLayout.Alignment;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JColorChooser;
import javax.swing.JComboBox;
import javax.swing.JInternalFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.SwingConstants;
import javax.swing.border.TitledBorder;
import javax.swing.colorchooser.AbstractColorChooserPanel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;
import javax.swing.text.StyledEditorKit.AlignmentAction;

/**
 * This class creates GUI for how the font selection will look. Allign the components
 * 	correctly and adds actionListener and changeListener to those components that
 * 	need it.
 * 
 * @author morten, kristofers, eigil
 *
 */
public class FontSelector extends JInternalFrame implements ChangeListener {
	private static ResourceBundle messages;
	private GridBagLayout mainLayout = new GridBagLayout();
	private SimpleAttributeSet sas;
	private int fontID;
	
	//Constants for preferences
	static Preferences pref;
	private static final String COLORKEY = "color";
	private static final int COLORDEF = Color.BLACK.getRGB();
	private static final String	SIZEKEY = "size";
	private static final int SIZEDEF = 3;
	private static final String BOLDKEY = "bold";
	private static final boolean BOLDDEF = false;
	private static final String ITALICKEY = "italic";
	private static final boolean ITALICDEF = false;
	private static final String ULINEKEY = "underline";
	private static final boolean ULINEDEF = false;
	private static final String TYPEKEY= "textType";
	private static final String TYPEDEF = "Times New Roman";
	
	JColorChooser tcc;
	JButton ok, cancel;
	Integer[] size = {6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30};
	JComboBox<Integer> sizes;
	JComboBox<String> textTypes;
	JCheckBox bold, italic, underline;
	JPanel options, cancelok, mainPanel, textSizePanel, sizePanel, previewPanel;
	JTextPane text;	
	
	/**
	 * This is the constructor for this class. Makes preferences for saving. It
	 *  also sets the attributes to the correct font.
	 * 
	 * @param id - is the number that will declare this fontSelector and knowing
	 * 				which chat-text it's belong to.
	 */
	public FontSelector(int id) {	
		super(messages.getString("fontsTitlePartOne") + " - " + Fonts.titleNames[id], 
				true, true, false);

		// Gets a hashmap with program preferences
		pref = Preferences.userNodeForPackage(getClass());
		
		fontID = id;
		fontLayout();
		changePreviewText();
		Fonts.setFont(fontID, sas);
	
		this.setSize(500, 350);
		this.setResizable(false);
		this.setVisible(true);	
	}
	
	/**
	 * Adds all components to the fontWindow.
	 *  This function is managing all the components for
	 *  creating the GUI-window
	 */
	public void fontLayout() {
		mainPanel = new JPanel();
							
		mainPanel.add(okCancel());
		mainPanel.add(fontPreview());
		mainPanel.add(textTypesAndSizes());
		mainPanel.add(textOptions());
		mainPanel.add(colorChooser());		
		mainPanel.setLayout(mainLayout);
		//Adding the mainPanel which contains all components into the internal frame
		this.add(mainPanel);
	}
		
	/**
	 * Creating options for editing text and align them in window.
	 *  This panel contains the option bold, kursiv and underline
	 * @return - panel options
	 */
	private Component textOptions() {
		GridBagConstraints gbc = new GridBagConstraints();
		options = new JPanel();
		options.setLayout(new FlowLayout());
		//Creates options for text to chat window, aligning them and
		//	adds listeners to them to instantly discover changes.
		bold = new JCheckBox(messages.getString("fontSelectorCheckboxBold"));
		bold.setHorizontalTextPosition(SwingConstants.LEFT);
		bold.setSelected(pref.getBoolean(Fonts.fontNames[fontID] + BOLDKEY, BOLDDEF));
		bold.addChangeListener(this);
		
		italic = new JCheckBox(messages.getString("fontSelectorCheckboxItalic"));
		italic.setHorizontalTextPosition(SwingConstants.LEFT);
		italic.setSelected(pref.getBoolean(Fonts.fontNames[fontID] + ITALICKEY, ITALICDEF));
		italic.addChangeListener(this);
		
		underline = new JCheckBox(messages.getString("fontSelectorCheckboxUnderline"));
		underline.setHorizontalTextPosition(SwingConstants.LEFT);
		underline.setSelected(pref.getBoolean(Fonts.fontNames[fontID] + ULINEKEY, ULINEDEF));
		underline.addChangeListener(this);
		//Setting gridbagconstrains for place them correctly in the frame.
		gbc.gridy = 1;
		gbc.gridx = 0;
		gbc.gridwidth = 3;
		gbc.insets = new Insets(2, 2, 2, 2);
		gbc.anchor = GridBagConstraints.CENTER;
		mainLayout.setConstraints(options, gbc);
		//Adding the options and return the panel
		options.add(bold);
		options.add(italic);
		options.add(underline);
		return options;		
	}
	
	/**
	 * Creating and aligning the panel containing two buttons.
	 * @return - panel cancelOk 
	 */
	private Component okCancel() {
		GridBagConstraints gbc = new GridBagConstraints();
		JPanel cancelOk = new JPanel();
		cancelOk.setLayout(new BorderLayout());
		//Creating the cancel button and sets an abstractaction to know what to do when pushed
		cancel = new JButton(messages.getString("fontSelectorButtonCancel"));
		AbstractAction cancelAct = new AbstractAction(messages.getString("fontSelectorButtonCancel")) {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				Main.win.md.remove(FontSelector.this);
				Main.win.md.repaint();
			}
		};
		cancel.setAction(cancelAct);
		//Creating the ok button and sets an abstractaction to know what to do when pushed
		ok = new JButton(messages.getString("fontSelectorButtonOk"));
		AbstractAction okAct = new AbstractAction(messages.getString("fontSelectorButtonOk")) {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				Fonts.setFont(fontID, sas);
				Main.win.md.remove(FontSelector.this);
				Main.win.md.repaint();
				savePref();
			}
		};
		ok.setAction(okAct);
		ok.setPreferredSize(cancel.getPreferredSize());
		//Aligning the panel in the GridBagLayout with gridbagconstraints gbc
		gbc.gridx = 0;
		gbc.gridy = 5;
		gbc.gridwidth = 3;
		gbc.insets = new Insets(2, 2, 2, 2);
		gbc.anchor = GridBagConstraints.CENTER;
		mainLayout.setConstraints(cancelOk, gbc);
		//Adding the buttons to the panel and return the panel
		cancelOk.add(cancel, BorderLayout.EAST);
		cancelOk.add(ok, BorderLayout.WEST);
		return cancelOk;
	}
	
	/**
	 * Creating and aligning for editing size and style for text.
	 * @return - panel textSizePanel
	 */
	private Component textTypesAndSizes() {
		GridBagConstraints gbc = new GridBagConstraints();
		textSizePanel = new JPanel();
		textTypes = new JComboBox<String>(GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames());
		textTypes.setSelectedItem(pref.get(Fonts.fontNames[fontID] + TYPEKEY, TYPEDEF));
		//Adds action listener for when textTypes changes
		textTypes.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				changePreviewText();
			}
		});
		textTypes.setEditable(true);
		sizes = new JComboBox<Integer>(size);
		sizes.setSelectedIndex(pref.getInt(Fonts.fontNames[fontID] + SIZEKEY, SIZEDEF));
		//Adds action listener for when size changes
		sizes.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				changePreviewText();
			}
		});
		sizes.setEditable(false);
		//Aligning the panel in the Gridbaglayout with gridbagconstraints gbc
		gbc.gridx = 0;
		gbc.gridy = 2;
		gbc.gridwidth = 3;
		gbc.anchor = GridBagConstraints.CENTER;
		mainLayout.setConstraints(textSizePanel, gbc);
		//Adds the two object to the panel and returns the panel
		textSizePanel.add(textTypes);
		textSizePanel.add(sizes);
		return textSizePanel;
	}
	
	/**
	 * Creating and aligning the preview of the text
	 * @return - panel fontPreview
	 */
	private Component fontPreview() {
		GridBagConstraints gbc = new GridBagConstraints();
		previewPanel = new JPanel();
		previewPanel.setLayout(new GridLayout(1, 1));
		
		text = new JTextPane();
		text.setEditable(false);
		
		//Creating default for how the text will look like
		SimpleAttributeSet defaultSet = new SimpleAttributeSet();
		StyleConstants.setFontFamily(defaultSet, "Times New Roman");
		StyleConstants.setFontSize(defaultSet, 12);
		StyleConstants.setForeground(defaultSet, Color.BLACK);
		StyleConstants.setAlignment(defaultSet, StyleConstants.ALIGN_CENTER);
		text.setText(messages.getString("fontSelectorPreviewText"));
		text.setCharacterAttributes(defaultSet, false);
		//Creating a borderline around the preview
		TitledBorder t = BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.black), 
				messages.getString("fontSelectorTextareaPreview"));
		t.setTitleJustification(TitledBorder.CENTER);
		t.setTitlePosition(TitledBorder.CENTER);
		previewPanel.setBorder(t);
		//Aligning int the gridbaglayout with gridbagconstraints gbc
		gbc.gridx = 0;
		gbc.gridy = 3;
		gbc.fill = GridBagConstraints.BOTH;
		gbc.insets = new Insets(1, 1, 1, 1);
		gbc.gridwidth = 3;
		mainLayout.setConstraints(previewPanel, gbc);
		//Adding the TextPane to the panel and returns the panel
		previewPanel.add(text);
		return previewPanel;
	}

	/**
	 * Grabbing object from a JColorChooser and uses only the colors.
	 * @return - JColorChooser tcc
	 */
	private Component colorChooser() {
		AbstractColorChooserPanel p[];
		GridBagConstraints gbc = new GridBagConstraints();
		
		tcc = new JColorChooser();
		//setting preview panel in JColorChooser to a blank panel
		// just to get rid of it
		tcc.setPreviewPanel(new JPanel());
		p = tcc.getChooserPanels();
		//Choosing panel in tray 0 (which is swatches)
		p = new AbstractColorChooserPanel[] {p[0]};
		tcc.setChooserPanels(p);
		//Adding changelistener to know if the state changes
		tcc.getSelectionModel().addChangeListener(this);
		//Setting the color to a default value
		tcc.setColor(new Color(pref.getInt(Fonts.fontNames[fontID] + COLORKEY, COLORDEF)));
		
		gbc.gridx = 0;
		gbc.gridy = 0;
		gbc.gridwidth = 3;
	    gbc.fill = GridBagConstraints.BOTH;
	    mainLayout.setConstraints(tcc, gbc);
		
		return tcc;
	}
	
	/**
	 * Function to be called when any state changes. Uses a SimpleAttributeSet
	 *  that get different StyleConstants and at last sets the text with those values.
	 */
	protected void changePreviewText() {
		String text2 = messages.getString("fontSelectorPreviewText");
		// A SimpleAttributeSet contains information about the styling to be used when adding new text
		// (or changing selected text.)
		sas = new SimpleAttributeSet ();
		StyleConstants.setFontFamily (sas, (String) textTypes.getSelectedItem());
		StyleConstants.setFontSize (sas, size[(Integer)sizes.getSelectedIndex()]);
		StyleConstants.setBold(sas, bold.isSelected());
		StyleConstants.setItalic(sas, italic.isSelected());
		StyleConstants.setUnderline(sas, underline.isSelected());
		StyleConstants.setForeground(sas, tcc.getColor());
		//Sets the charAtt sas to the text
		text.setCharacterAttributes(sas, true);
		text.setText(text2);
	}
	
	/**
	 * For internationalization of the program
	 * @param m - ResourceBundle
	 */
	public static void setMessages(ResourceBundle m) {
		FontSelector.messages = m;
	}

	/* (non-Javadoc)
	 * @see javax.swing.event.ChangeListener#stateChanged(javax.swing.event.ChangeEvent)
	 */
	@Override
	public void stateChanged(ChangeEvent arg0) {
		changePreviewText();
	}
	
	/**
	 * This function saves the attributes that changes the fonts on the text
	 *  to the register. Different chat text, then also a different save.
	 */
	public void savePref() {
		pref.put(Fonts.fontNames[fontID] + TYPEKEY, (String) textTypes.getSelectedItem());
		pref.putInt(Fonts.fontNames[fontID] + SIZEKEY, sizes.getSelectedIndex());
		pref.putInt(Fonts.fontNames[fontID] + COLORKEY, tcc.getColor().getRGB());
		pref.putBoolean(Fonts.fontNames[fontID] + BOLDKEY, bold.isSelected());
		pref.putBoolean(Fonts.fontNames[fontID] + ITALICKEY, italic.isSelected());
		pref.putBoolean(Fonts.fontNames[fontID] + ULINEKEY, underline.isSelected());
	}
}
